<?php

require __DIR__.'/bootstrap/autoload.php';

class Server
{
    static $kernel;
    public function __construct($ip,$port)
    {
        $server = new swoole_http_server($ip, $port);
        $server->set([
            'reactor_num '=>1,//cpu核数
            'worker_num'=>1,//异步下为CPU核数的1-4倍
            'document_root' => '/webroot/www/laravel5.4/public',//根据实际情况设置
            'enable_static_handler' => true,
        ]);
        $server->on('WorkerStart', array($this, 'start'));
        $server->on('request', array($this, 'request'));
        $server->start();
    }

    public static function start($server, $worker_id)
    {
        
        $app = require_once __DIR__.'/bootstrap/app.php';
        self::$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
        //var_dump($server->setting);//不要打印$server,会一直输出
        //var_dump($worker_id);//worker进程编号
    }

    public static function request($request, $response)
    {
        //由于swoole的get post这些请求封装的和php原生的不一样,需要修改
        Illuminate\Http\Request::enableHttpMethodParameterOverride();
        if ('cli-server' === PHP_SAPI) {
            if (array_key_exists('HTTP_CONTENT_LENGTH', $request->server)) {
                $server['CONTENT_LENGTH'] = $request->server['HTTP_CONTENT_LENGTH'];
            }
            if (array_key_exists('HTTP_CONTENT_TYPE', $request->server)) {
                $server['CONTENT_TYPE'] = $request->server['HTTP_CONTENT_TYPE'];
            }
        }

        $server=[];
        if(isset($request->server)){
            foreach($request->server as $k=>$val){
                $server[strtoupper($k)]=$val;
            }
        }

        $headerMap = [
            'x-real-ip'       => 'REMOTE_ADDR',
            'x-real-port'     => 'REMOTE_PORT',
            'server-protocol' => 'SERVER_PROTOCOL',
            'server-name'     => 'SERVER_NAME',
            'server-addr'     => 'SERVER_ADDR',
            'server-port'     => 'SERVER_PORT',
            'scheme'          => 'REQUEST_SCHEME',
        ];

        if(isset($request->header)){
            foreach($request->header as $k=>$val){
                if (isset($headerMap[$k])) {
                    $server[$headerMap[$k]] = $val;
                } else {
                    $key = str_replace('-', '_', $k);
                    $key = "http_".$key;
                    $server[strtoupper($key)]=$val;
                }

            }
        }


        $get = [];
        if(isset($request->get)){
            foreach($request->get as $k=>$val){
                $get[$k]=$val;
            }
        }
        $post = [];
        if(isset($request->post)){
            foreach($request->post as $k=>$val){
                $post[$k]=$val;
            }
        }

        $cookie =[];
        if(isset($request->cookie)){
            foreach($request->cookie as $k=>$val){
                $cookie[$k]=$val;
            }
        }


        $files =[];
        if(isset($request->files)){
            $files = $request->files;
        }


        $laravel_request= new Symfony\Component\HttpFoundation\Request($get,$post,[],$cookie,$files,$server);
        if (0 === strpos($laravel_request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
            && in_array(strtoupper($laravel_request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
        ) {
            parse_str($laravel_request->getContent(), $data);
            $laravel_request->request = new Symfony\Component\HttpFoundation\ParameterBag($data);
        }

        $laravel_request=Illuminate\Http\Request::createFromBase($laravel_request);

        ob_start();
        $laravel_response = self::$kernel->handle($laravel_request);
        $content = $laravel_response->getContent();
        self::$kernel->terminate($laravel_request, $laravel_response);
        $result = ob_get_contents();
        if (strlen($content) == 0 && ob_get_length() > 0) {
            $laravel_response->setContent($result);//判断内容长度是否为0，为0则代表为var_dump输出内容
        }
        //ob_end_clean();
        if (ob_get_contents()) ob_end_clean();
        if ($laravel_request->hasSession()) {
            $session = $laravel_request->getSession();
            $session->flush();
        }
        self::send($laravel_response,$response);
        $response->end($laravel_response->getContent());
        //$response->end($content.$result);

    }

    public static function send($laravel_response, $response)
    {
        $response->status($laravel_response->getStatusCode());
        foreach ($laravel_response->headers->allPreserveCase() as $name => $values) {
            foreach ($values as $value) {
                $response->header($name, $value);
            }
        }

        foreach ($laravel_response->headers->getCookies() as $cookie) {
            $response->cookie(
                $cookie->getName(),
                $cookie->getValue(),
                $cookie->getExpiresTime(),
                $cookie->getPath(),
                $cookie->getDomain(),
                $cookie->isSecure(),
                $cookie->isHttpOnly()
            );
        }
    }

}

$server=new Server('0.0.0.0',9090);